﻿using System;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;

namespace Lyon.EventMethods
{
    [Serializable]
    [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
    public class EventMethodAttribute : Attribute
    {
        static public EventMethodAttribute Default = new EventMethodAttribute() { IgnoreReturn = false, Timeout = 30000 };

        public bool IgnoreReturn;
        public int Timeout;
    }
    [Serializable]
    public class EventMethodHandle
    {
        public bool IsProxy;
        public string Value;
    }
    [Serializable]
    public class EventMethodCall : System.Runtime.Serialization.ISerializable
    {
        public string ID;
        public string Url;
        public Type UrlType;
        public MethodInfo Method;
        public object[] Args;
        public bool IgnoreReturn;

        public EventMethodCall() { }
        protected EventMethodCall(SerializationInfo info, StreamingContext ctx)
        {
            ID = info.GetString("ID");
            Url = info.GetString("Url");
            UrlType = Type.GetType(info.GetString("UrlType"));
            Method = Type.GetType(info.GetString("Method.DeclaringType")).GetMethod(info.GetString("Method.Name")
                , Array.ConvertAll<string, Type>((string[])info.GetValue("Method.Parameters", typeof(string[])), item => Type.GetType(item)));
            Args = (object[])info.GetValue("Args", typeof(object[]));
            IgnoreReturn = info.GetBoolean("IgnoreReturn");
        }
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("ID", ID);
            info.AddValue("Url", Url);
            info.AddValue("UrlType", UrlType.AssemblyQualifiedName);
            info.AddValue("Method.DeclaringType", Method.DeclaringType.AssemblyQualifiedName);
            info.AddValue("Method.Name", Method.Name);
            info.AddValue("Method.Parameters", Method.GetParameters().Select(item => item.ParameterType.AssemblyQualifiedName).ToArray());
            info.AddValue("Args", Args);
            info.AddValue("IgnoreReturn", IgnoreReturn);
        }
    }
    [Serializable]
    public class EventMethodReturn : System.Runtime.Serialization.ISerializable
    {
        public string CallID;
        public object ReturnValue;
        public Exception Exception;

        public EventMethodReturn() { }
        protected EventMethodReturn(SerializationInfo info, StreamingContext ctx)
        {
            CallID = info.GetString("CallID");
            ReturnValue = (object)info.GetValue("ReturnValue", typeof(object));
            Exception = (Exception)info.GetValue("Exception", typeof(Exception));
        }
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("CallID", CallID);
            info.AddValue("ReturnValue", ReturnValue, typeof(object));
            info.AddValue("Exception", Exception, typeof(Exception));
        }
    }
}